package org.tom.order.service.impl;

import org.apache.commons.lang3.time.DateUtils;
import org.quartz.Scheduler;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.tom.basic.exception.MyException;
import org.tom.basic.service.impl.BaseServiceImpl;
import org.tom.basic.util.LoginContextUtil;
import org.tom.order.domain.OrderAddress;
import org.tom.order.domain.OrderPet;
import org.tom.order.domain.OrderPetDetail;
import org.tom.order.dto.SaveOrderDto;
import org.tom.order.mapper.OrderPetAddressMapper;
import org.tom.order.mapper.OrderPetDetailMapper;
import org.tom.order.mapper.OrderPetMapper;
import org.tom.order.service.IOrderPetService;
import org.tom.org.domain.Shop;
import org.tom.org.mapper.ShopMapper;
import org.tom.pay.domain.PayBill;
import org.tom.pay.service.IPayBillService;
import org.tom.pet.constant.PetConstant;
import org.tom.pet.domain.Pet;
import org.tom.pet.mapper.PetMapper;
import org.tom.quartz.job.OrderExpireJob;
import org.tom.quartz.service.IQuartzService;
import org.tom.quartz.util.QuartzUtil;
import org.tom.user.domain.Logininfo;
import org.tom.user.domain.UserAddress;
import org.tom.user.mapper.UserAddressMapper;

import java.math.BigDecimal;
import java.util.Date;
import java.util.HashMap;
import java.util.UUID;

@Service
@Transactional(readOnly = true,propagation = Propagation.SUPPORTS)
public class OrderPetServiceImpl extends BaseServiceImpl<OrderPet> implements IOrderPetService {
    @Autowired
    private IQuartzService quartzService;

    @Autowired
    private Scheduler scheduler;

    @Autowired
    private IPayBillService payBillService;

    @Autowired
    private ShopMapper shopMapper;

    @Autowired
    private OrderPetMapper orderPetMapper;
    
    @Autowired
    private PetMapper petMapper;

    @Autowired
    private OrderPetAddressMapper orderPetAddressMapper;

    @Autowired
    private UserAddressMapper userAddressMapper;

    @Autowired
    private OrderPetDetailMapper orderPetDetailMapper;

    @Override
    @Transactional
    public String commitPetOrder(SaveOrderDto saveOrderDto) {
        Long addressId = saveOrderDto.getAddressId();
        Integer payType = saveOrderDto.getPayType();
        Long petId = saveOrderDto.getPetId();
        // 非空判断
        if (petId == null){
            throw new MyException("宠物不存在");
        }
        if (payType == null){
            throw new MyException("支付类型不存在");
        }
        if (addressId == null){
            throw new MyException("地址异常");
        }

        // 查询宠物，只能查询上架的宠物，如果是没上架的不进行判断的话，通过postman可以直接访问我的数据库
        Pet pet = petMapper.loadPetByStateAndId(petId, PetConstant.ONLINE);
        if (pet == null){
            throw new MyException("错误的商品");
        }

        // 查询地址
        UserAddress userAddress = userAddressMapper.loadOneAddressById(addressId);
        if (userAddress == null){
            throw new MyException("错误的地址");
        }

        // 创建订单表填入数据
        OrderPet orderPet = new OrderPet();
        orderPet.setDigest("购买：" + pet.getName());
        orderPet.setState(OrderPet.WAIT_PAY_ORDER);
        Date now = new Date();
        orderPet.setCreateTime(now);
        // 15分钟自动关闭
        Date expireTime = DateUtils.addMinutes(now, 15);
        orderPet.setPayExpireTime(expireTime);
        // 生成随机的订单号，将-修改为空字符
        String sn = UUID.randomUUID().toString().replaceAll("-", "");
        orderPet.setOrderSn(sn);

        orderPet.setPayType(payType);

        Logininfo logininfo = LoginContextUtil.getLoginContext();
        if (logininfo == null){
            // 防止别人使用postman访问
            throw new MyException("登录之后在再操作");
        }
        orderPet.setUserId(logininfo.getId());
        orderPet.setLastUpdateTime(now);

        // 商品总数暂时设置唯一，以后可以修改前端传一个集合过来，直接计数
        orderPet.setTotalCount(1);

        // 商品总价格邮费固定10，以后可以修改，商品价格的计算
        orderPet.setTotalPrice(pet.getSaleprice().add(new BigDecimal("10")));
        orderPetMapper.add(orderPet);

        //===============================================
        // 添加商品的详细信息
        OrderPetDetail orderPetDetail = new OrderPetDetail();
        orderPetDetail.setCount(1);
        orderPetDetail.setCreatetime(new Date());
        orderPetDetail.setName(pet.getName());
        orderPetDetail.setPetId(petId);
        orderPetDetail.setOrderId(orderPet.getId());
        orderPetDetail.setOrderSn(orderPet.getOrderSn());


        Pet pet1 = petMapper.loadById(petId);
        Shop shop = shopMapper.loadById(pet1.getShop_id());

        orderPetDetail.setShopId(shop.getId());
        orderPetDetail.setShopName(shop.getName());
        orderPetDetail.setPrice(pet.getSaleprice());
        orderPetDetail.setResources(pet.getResources());
        orderPetDetailMapper.add(orderPetDetail);

        // ==================================================
        // 保存到地址中
        OrderAddress orderAddress = new OrderAddress();
        BeanUtils.copyProperties(userAddress, orderAddress);
        orderAddress.setOrderId(orderPet.getId());
        orderAddress.setOrderSn(orderPet.getOrderSn());
        orderAddress.setCreateTime(now);
        orderPetAddressMapper.add(orderAddress);

        // =========================================
        // 修改库存
        synchronized (this){ // 为了防止多人同时购买导致的高并发所以使用线程锁，稍微有点问题，pet是变量每个线程都会创建，当两个线程一起进来的时候就会线程不安全，解决方案的就是在每次修改之前再差一次
            pet1 = petMapper.loadById(petId);
            if (pet1.getStore_number() != 0){
                pet1.setStore_number(pet1.getStore_number()-1);
                if (pet1.getStore_number() == 0){ // 当商品的库存为0的时候就下架商品
                    pet1.setState(PetConstant.OFFLINE);
                }
                petMapper.update(pet1);
            }else {
                throw new MyException("没有货了");
            }
        }

        // 创建保存订单Paybill
        payBillService.savePayBill(orderPet.getId(), PayBill.PET_BUY, orderPet.getCreateTime(),pet.getName(),orderPet.getTotalPrice(),logininfo.getId(),logininfo.getUsername(),payType,shop.getId(),shop.getName(),OrderPet.WAIT_PAY_ORDER, sn);

        // 订单超时的判断
        HashMap<String, String> map = new HashMap<>();
        map.put("sn", sn);
        // scheduler 调度器,sn 任务名, OrderExpireJob.class 任务，一个job类, map里面放的任务参数, expireTime 时间的设置这里设置的时间就是订单超时的时间
        QuartzUtil.addJob(scheduler,sn, OrderExpireJob.class, map, expireTime);
        return sn;

    }
}
